/*
 * @Author: cyfqyb
 * @Date: 2023-10-24 16:59:36
 * @LastEditors: cyfqyb cy15770703229@163.com
 * @LastEditTime: 2023-10-25 14:12:09
 * @FilePath: \ImBackend\test\test2.ts
 * @Description: 介绍
 */
class Promise2 {
  constructor(
    executor: (
      resolve: (value?: any) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    this.PromiseStatus = "pending";
    this.PromiseValue = null;
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
    try {
      executor(this.resolve, this.reject);
    } catch (e) {
      this.reject(e);
    }
  }
  //状态
  PromiseStatus: "pending" | "fulfilled" | "rejected";
  //保存的值
  PromiseValue: any;
  //保存回调函数
  onFufiledCallbacks: Array<any> = [];
  onRejectedCallbacks: Array<any> = [];
  resolve(value?: any) {
    if (this.PromiseStatus !== "pending") return;
    this.PromiseStatus = "fulfilled";
    this.PromiseValue = value;
    while (this.onFufiledCallbacks.length)
      this.onFufiledCallbacks.shift()?.(this.PromiseValue);
  }
  reject(reason?: any) {
    if (this.PromiseStatus !== "pending") return;
    this.PromiseStatus = "rejected";
    this.PromiseValue = reason;
    while (this.onRejectedCallbacks.length)
      this.onRejectedCallbacks.shift()?.(this.PromiseValue);
  }
  then(onFufiled?: (value: any) => any, onRejected?: (reason: any) => any) {
    onFufiled =
      typeof onFufiled === "function" ? onFufiled : (value: any) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason: any) => {
            throw reason;
          };
    return new Promise2((resolve, reject) => {
      const resolvePromise = (cb: any) => {
        setTimeout(() => {
          try {
            const result = cb(this.PromiseValue);
            if (result === this) throw new TypeError("循环引用");
            if (result instanceof Promise2) result.then(resolve, reject);
            else resolve(result);
          } catch (error: any) {
            reject(error);
          }
        });
      };
      if (this.PromiseStatus === "fulfilled") resolvePromise(onFufiled);
      else if (this.PromiseStatus === "rejected") resolvePromise(onRejected);
      else {
        this.onFufiledCallbacks.push(onFufiled);
        this.onRejectedCallbacks.push(onRejected);
      }
    });
  }
  catch(onRejected: (reason: any) => any) {
    return this.then(undefined, onRejected);
  }
  static all(promises: Promise2[]) {
    const resultPromise = new Promise2((resolve, reject) => {
      const result: Array<any> = [];
      let count = 0;
      promises.forEach((promise, index) => {
        promise.then((res) => {
          result[index] = res;
          if (++count === promises.length) resolve(result);
        }, reject);
      });
    });
    return resultPromise;
  }
  static race(promises: Promise2[]) {
    return new Promise2((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(resolve, reject);
      });
    });
  }
}
const p1 = new Promise2((resolve) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});
const p2 = new Promise2((resolve, reject) => {
  setTimeout(() => {
    reject("报错");
    resolve(1);
  }, 500);
});
const demo = Promise2.race([p1, p2]).then((err) => {
  console.log(err);
  console.log(demo.PromiseStatus);
});
